<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Compatibility</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Compatibility' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.html">Services</a></li><li><a href="index.html">arch</a></li><li><a href="index.html#2">Chapter 2: Architectures and VMs</a></li><li><b>Compatibility</b></li></ul></div>
<p class="purpose">To manage specifications of compatibility with some VMs but not others.</p>

<ul class="toc"><li><a href="2-cmp.html#SP1">&#167;1. Specifications</a></li><li><a href="2-cmp.html#SP5">&#167;5. Converting to text</a></li><li><a href="2-cmp.html#SP6">&#167;6. Converting from text</a></li><li><a href="2-cmp.html#SP11">&#167;11. Testing</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Specifications.</b>An object of the following class can represent any subset of VMs, so
it's a fully general way to express which VMs some piece of software works with:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parsed_from</span><span class="plain-syntax">; </span><span class="comment-syntax"> if it came from text</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">default_allows</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">exceptions</span><span class="plain-syntax">; </span><span class="comment-syntax"> of </span><span class="extract"><span class="extract-syntax">target_vm</span></span>
<span class="plain-syntax">    </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure compatibility_specification is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>The creator function for this always begins with a specification meaning
"works with all VMs":
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="function-syntax">Compatibility::all</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Compatibility::all</span></span>:<br/><a href="2-cmp.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_from</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">default_allows</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">exceptions</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEW_LINKED_LIST</span><span class="plain-syntax">(</span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">C</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>We can then change this in two ways: one is to reverse the default...
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::reverse</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Compatibility::reverse</span></span>:<br/><a href="2-cmp.html#SP6">&#167;6</a>, <a href="2-cmp.html#SP6_2_1">&#167;6.2.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">default_allows</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">default_allows</span><span class="plain-syntax">)?</span><span class="identifier-syntax">FALSE:TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>...and the other is to add an exception:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::add_exception</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Compatibility::add_exception</span></span>:<br/><a href="2-cmp.html#SP10_1">&#167;10.1</a>, <a href="2-cmp.html#SP10_2">&#167;10.2</a>, <a href="2-cmp.html#SP10_3">&#167;10.3</a>, <a href="2-cmp.html#SP10_5">&#167;10.5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VM</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">already_there</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">, </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">exceptions</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">VM</span><span class="plain-syntax"> == </span><span class="identifier-syntax">X</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">already_there</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">already_there</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">ADD_TO_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">, </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">exceptions</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">already_there</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. Converting to text.</b>This often produces something verbose; the <span class="extract"><span class="extract-syntax">parsed_from</span></span> text probably reads
better, if available.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::write</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">C</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"for none"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">x</span><span class="plain-syntax"> = </span><span class="identifier-syntax">LinkedLists::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">exceptions</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">x</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">default_allows</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"for all"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"for none"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">default_allows</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"not "</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"for "</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">n</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">, </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">exceptions</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">n</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">n</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">n</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">x</span><span class="plain-syntax">)) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">", "</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">n</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">n</span><span class="plain-syntax"> == </span><span class="identifier-syntax">x</span><span class="plain-syntax">)) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">" or "</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><a href="2-tvm.html#SP5" class="function-link"><span class="function-syntax">TargetVMs::write</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">VM</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. Converting from text.</b>This is quite a tricky little parser, which has to read, for example,
text like "for Glulx only" used in Inform extension headings. A syntactically
invalid description returns <span class="extract"><span class="extract-syntax">NULL</span></span> but prints no error message; an empty
description returns the universally valid specification.
</p>

<p class="commentary">A question we might return to is whether an unrecognisable description &mdash;
say, "for Marzipan version 28.1 only" &mdash; should return a universally-false
specification rather than returning <span class="extract"><span class="extract-syntax">NULL</span></span>: this would enable current Inform
tools to work with future resources which use VMs currently unthought of.
But for now, it seems best to generate errors, because the more likely thing
is that an extension author is botching the wording of something, or
writing "Z machine" instead of "Z-machine", or something like that.
</p>

<p class="commentary">It might seem better to all of this with a Preform grammar, rather than by
hand. But we want to make it work in tools which don't have Preform available,
and we want it to run quickly.
</p>

<p class="commentary">Unless the text is empty, we start with the "works with nothing" specification
and then add each VM with which <span class="extract"><span class="extract-syntax">C</span></span> does work as an exception.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="function-syntax">Compatibility::from_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">text</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax"> = </span><a href="2-cmp.html#SP2" class="function-link"><span class="function-syntax">Compatibility::all</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parsed_from</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Str::duplicate</span><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">C</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><a href="2-cmp.html#SP3" class="function-link"><span class="function-syntax">Compatibility::reverse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">C</span><span class="plain-syntax">); </span><span class="comment-syntax"> now </span><span class="extract"><span class="extract-syntax">C</span></span><span class="comment-syntax"> works with nothing</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">error_in_syntax</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">match_results</span><span class="plain-syntax"> </span><span class="identifier-syntax">mr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Regexp::create_mr</span><span class="plain-syntax">();</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">, </span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">text</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP6_1" class="named-paragraph-link"><span class="named-paragraph">Remove excess space and/or enclosing brackets and lower in case</span><span class="named-paragraph-number">6.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP6_2" class="named-paragraph-link"><span class="named-paragraph">Actually parse the description</span><span class="named-paragraph-number">6.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Regexp::dispose_of</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">error_in_syntax</span><span class="plain-syntax">)?</span><span class="identifier-syntax">NULL:C</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6_1" class="paragraph-anchor"></a><b>&#167;6.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Remove excess space and/or enclosing brackets and lower in case</span><span class="named-paragraph-number">6.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">Str::trim_white_space</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Str::get_first_char</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">) == </span><span class="character-syntax">'('</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">Str::get_last_char</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">) == </span><span class="character-syntax">')'</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::delete_first_character</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::delete_last_character</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::trim_white_space</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_THROUGH_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::put</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">Characters::tolower</span><span class="plain-syntax">(</span><span class="identifier-syntax">Str::get</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">)));</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP6">&#167;6</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_2" class="paragraph-anchor"></a><b>&#167;6.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Actually parse the description</span><span class="named-paragraph-number">6.2</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">negated</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP6_2_1" class="named-paragraph-link"><span class="named-paragraph">Parse out the prefix not</span><span class="named-paragraph-number">6.2.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP6_2_2" class="named-paragraph-link"><span class="named-paragraph">Remove the meaningless word for</span><span class="named-paragraph-number">6.2.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP6_2_3" class="named-paragraph-link"><span class="named-paragraph">Parse out the suffix only</span><span class="named-paragraph-number">6.2.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::eq</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"all"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">negated</span><span class="plain-syntax">) </span><span class="identifier-syntax">error_in_syntax</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="comment-syntax"> "not for all"</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">default_allows</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::eq</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"none"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">negated</span><span class="plain-syntax">) </span><span class="identifier-syntax">error_in_syntax</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="comment-syntax"> "not for none"</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">default_allows</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-cmp.html#SP8" class="function-link"><span class="function-syntax">Compatibility::parse_specifics</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">C</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">error_in_syntax</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP6">&#167;6</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_2_1" class="paragraph-anchor"></a><b>&#167;6.2.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse out the prefix not</span><span class="named-paragraph-number">6.2.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Regexp::match</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse</span><span class="plain-syntax">, </span><span class="identifier-syntax">U</span><span class="string-syntax">"not (%c+)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::clear</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">, </span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[0]);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::trim_white_space</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><a href="2-cmp.html#SP3" class="function-link"><span class="function-syntax">Compatibility::reverse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">C</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">negated</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP6_2">&#167;6.2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_2_2" class="paragraph-anchor"></a><b>&#167;6.2.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Remove the meaningless word for</span><span class="named-paragraph-number">6.2.2</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Regexp::match</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse</span><span class="plain-syntax">, </span><span class="identifier-syntax">U</span><span class="string-syntax">"for (%c+)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::clear</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">, </span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[0]);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::trim_white_space</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP6_2">&#167;6.2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6_2_3" class="paragraph-anchor"></a><b>&#167;6.2.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse out the suffix only</span><span class="named-paragraph-number">6.2.3</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Regexp::match</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse</span><span class="plain-syntax">, </span><span class="identifier-syntax">U</span><span class="string-syntax">"(%c+) only"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::clear</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">, </span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[0]);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::trim_white_space</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">negated</span><span class="plain-syntax">) </span><span class="identifier-syntax">error_in_syntax</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="comment-syntax"> "not for 32d only"</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP6_2">&#167;6.2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b>The above gets us down from, say, "for Glulx only" to just "Glulx", and
calls the function <a href="2-cmp.html#SP8" class="internal">Compatibility::parse_specifics</a> to handle that specific part &mdash;
though it may be more complicated. See the <a href="../arch-test/index.html" class="internal">arch-test</a> unit test for
examples. While parsing those specifics we maintain a state in the following
structure:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">compat_parser_state</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">current_family</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">version_allowed</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">version_required</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">family_used</span><span class="plain-syntax">;</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">compat_parser_state</span><span class="plain-syntax">;</span>

<span class="reserved-syntax">compat_parser_state</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::initial_state</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">Compatibility::initial_state</span></span>:<br/><a href="2-cmp.html#SP8">&#167;8</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">compat_parser_state</span><span class="plain-syntax"> </span><span class="identifier-syntax">cps</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">.</span><span class="element-syntax">C</span><span class="plain-syntax"> = </span><span class="identifier-syntax">C</span><span class="plain-syntax">; </span><span class="identifier-syntax">cps</span><span class="plain-syntax">.</span><span class="element-syntax">version_allowed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">; </span><span class="identifier-syntax">cps</span><span class="plain-syntax">.</span><span class="element-syntax">version_required</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">.</span><span class="element-syntax">current_family</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="identifier-syntax">cps</span><span class="plain-syntax">.</span><span class="element-syntax">family_used</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">cps</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>The structure compat_parser_state is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b>So here's the specific details parser, then. We return <span class="extract"><span class="extract-syntax">TRUE</span></span> if no syntax
errors occurred, and we change <span class="extract"><span class="extract-syntax">C</span></span> according to what <span class="extract"><span class="extract-syntax">text</span></span> says.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::parse_specifics</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Compatibility::parse_specifics</span></span>:<br/><a href="2-cmp.html#SP6_2">&#167;6.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">text</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">okay</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">match_results</span><span class="plain-syntax"> </span><span class="identifier-syntax">mr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Regexp::create_mr</span><span class="plain-syntax">();</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">compat_parser_state</span><span class="plain-syntax"> </span><span class="identifier-syntax">cps</span><span class="plain-syntax"> = </span><a href="2-cmp.html#SP7" class="function-link"><span class="function-syntax">Compatibility::initial_state</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">C</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP8_1" class="named-paragraph-link"><span class="named-paragraph">Reduce the text to a sequence of tokens</span><span class="named-paragraph-number">8.1</span></a></span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">Regexp::dispose_of</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">okay</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8_1" class="paragraph-anchor"></a><b>&#167;8.1. </b>This is essentially simple &mdash; it splits up text like "Z-machine versions 5 or 8"
into tokens, sending them one at a time to <a href="2-cmp.html#SP10" class="internal">Compatibility::parse_token</a>.
Note that commas are converted to the token <span class="extract"><span class="extract-syntax">or</span></span>: e.g., "Z-machine versions 5, 6
or 8" would be treated as "Z-machine versions 5 or 6 or 8"; and note also that
"with debugging" and "without debugging" are handled specially.
</p>

<p class="commentary">We end the sequence of tokens with a <span class="extract"><span class="extract-syntax">NULL</span></span>, telling the token-parser that
it has reached the end.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Reduce the text to a sequence of tokens</span><span class="named-paragraph-number">8.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Regexp::match</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="identifier-syntax">U</span><span class="string-syntax">"(%C+) (%c+)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">comma</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::get_last_char</span><span class="plain-syntax">(</span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[0]) == </span><span class="character-syntax">','</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">comma</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Str::delete_last_character</span><span class="plain-syntax">(</span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[0]);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Str::trim_white_space</span><span class="plain-syntax">(</span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[0]);</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">with</span><span class="plain-syntax"> = </span><a href="2-cmp.html#SP9" class="function-link"><span class="function-syntax">Compatibility::parse_debugging</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[1]);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">okay</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">okay</span><span class="plain-syntax"> &amp;&amp; </span><a href="2-cmp.html#SP10" class="function-link"><span class="function-syntax">Compatibility::parse_token</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">cps</span><span class="plain-syntax">, </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[0], </span><span class="identifier-syntax">with</span><span class="plain-syntax">));</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">comma</span><span class="plain-syntax">) </span><span class="identifier-syntax">okay</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">okay</span><span class="plain-syntax"> &amp;&amp; </span><a href="2-cmp.html#SP10" class="function-link"><span class="function-syntax">Compatibility::parse_token</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">cps</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"or"</span><span class="plain-syntax">, </span><span class="identifier-syntax">with</span><span class="plain-syntax">));</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::clear</span><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">); </span><span class="identifier-syntax">Str::copy</span><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[1]);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">okay</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">okay</span><span class="plain-syntax"> &amp;&amp; </span><a href="2-cmp.html#SP10" class="function-link"><span class="function-syntax">Compatibility::parse_token</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">cps</span><span class="plain-syntax">, </span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">okay</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">okay</span><span class="plain-syntax"> &amp;&amp; </span><a href="2-cmp.html#SP10" class="function-link"><span class="function-syntax">Compatibility::parse_token</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">cps</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">));</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP8">&#167;8</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. </b>Returns <span class="extract"><span class="extract-syntax">TRUE</span></span> if the text <span class="extract"><span class="extract-syntax">T</span></span> begins "with debugging", and trims that text
away from <span class="extract"><span class="extract-syntax">T</span></span>; returns <span class="extract"><span class="extract-syntax">FALSE</span></span> if it begins "without debugging", and similarly
trims; and otherwise returns <span class="extract"><span class="extract-syntax">NOT_APPLICABLE</span></span> and leaves <span class="extract"><span class="extract-syntax">T</span></span> unaltered.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::parse_debugging</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">Compatibility::parse_debugging</span></span>:<br/><a href="2-cmp.html#SP8_1">&#167;8.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">with</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">match_results</span><span class="plain-syntax"> </span><span class="identifier-syntax">mr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Regexp::create_mr</span><span class="plain-syntax">();</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Regexp::match</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">U</span><span class="string-syntax">"with debugging,* *(%c*)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::clear</span><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::copy</span><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[0]);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">with</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Regexp::match</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">U</span><span class="string-syntax">"without debugging,* *(%c*)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::clear</span><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Str::copy</span><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="identifier-syntax">exp</span><span class="plain-syntax">[0]);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">with</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Regexp::dispose_of</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">with</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. </b>Once again we return <span class="extract"><span class="extract-syntax">TRUE</span></span> if no syntax errors occurred, and we change <span class="extract"><span class="extract-syntax">C</span></span>
according to what the <span class="extract"><span class="extract-syntax">token</span></span> says.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::parse_token</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Compatibility::parse_token</span></span>:<br/><a href="2-cmp.html#SP8_1">&#167;8.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">compat_parser_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">cps</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">token</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">with</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">token</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP10_5" class="named-paragraph-link"><span class="named-paragraph">Construe the token as the end-marker</span><span class="named-paragraph-number">10.5</span></a></span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">version_allowed</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">semantic_version_number</span><span class="plain-syntax"> </span><span class="identifier-syntax">V</span><span class="plain-syntax"> = </span><span class="identifier-syntax">VersionNumbers::from_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">token</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">VersionNumbers::is_null</span><span class="plain-syntax">(</span><span class="identifier-syntax">V</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">version_required</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">current_family</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP10_1" class="named-paragraph-link"><span class="named-paragraph">Construe token as a version number</span><span class="named-paragraph-number">10.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::eq_insensitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">token</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"or"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">with</span><span class="plain-syntax"> != </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Str::eq_insensitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">token</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"version"</span><span class="plain-syntax">)) ||</span>
<span class="plain-syntax">        (</span><span class="identifier-syntax">Str::eq_insensitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">token</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"versions"</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">with</span><span class="plain-syntax"> != </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">version_required</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">version_allowed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">version_required</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">version_allowed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bits</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::eq_insensitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">token</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"16-bit"</span><span class="plain-syntax">)) </span><span class="identifier-syntax">bits</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::eq_insensitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">token</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"z-machine"</span><span class="plain-syntax">)) </span><span class="identifier-syntax">bits</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::eq_insensitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">token</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"32-bit"</span><span class="plain-syntax">)) </span><span class="identifier-syntax">bits</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::eq_insensitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">token</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"glulx"</span><span class="plain-syntax">)) </span><span class="identifier-syntax">bits</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bits</span><span class="plain-syntax"> != </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP10_2" class="named-paragraph-link"><span class="named-paragraph">Construe token as a bit count</span><span class="named-paragraph-number">10.2</span></a></span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">with</span><span class="plain-syntax"> != </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP10_3" class="named-paragraph-link"><span class="named-paragraph">Construe token as a family name subject to debugging</span><span class="named-paragraph-number">10.3</span></a></span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-cmp.html#SP10_4" class="named-paragraph-link"><span class="named-paragraph">Construe token as a family name</span><span class="named-paragraph-number">10.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10_1" class="paragraph-anchor"></a><b>&#167;10.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Construe token as a version number</span><span class="named-paragraph-number">10.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">family_used</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">seen</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-tvm.html#SP15" class="function-link"><span class="function-syntax">TargetVMs::compatible_with</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">current_family</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">seen</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">VersionNumbers::eq</span><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">version</span><span class="plain-syntax">, </span><span class="identifier-syntax">V</span><span class="plain-syntax">)) &amp;&amp;</span>
<span class="plain-syntax">                ((</span><span class="identifier-syntax">with</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">) || (</span><a href="2-tvm.html#SP10" class="function-link"><span class="function-syntax">TargetVMs::debug_enabled</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">) == </span><span class="identifier-syntax">with</span><span class="plain-syntax">)))</span>
<span class="plain-syntax">                </span><a href="2-cmp.html#SP4" class="function-link"><span class="function-syntax">Compatibility::add_exception</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">C</span><span class="plain-syntax">, </span><span class="identifier-syntax">VM</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">version_required</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">seen</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP10">&#167;10</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP10_2" class="paragraph-anchor"></a><b>&#167;10.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Construe token as a bit count</span><span class="named-paragraph-number">10.2</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-tvm.html#SP10" class="function-link"><span class="function-syntax">TargetVMs::is_16_bit</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">) == </span><span class="identifier-syntax">bits</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">with</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NOT_APPLICABLE</span><span class="plain-syntax">) || (</span><a href="2-tvm.html#SP10" class="function-link"><span class="function-syntax">TargetVMs::debug_enabled</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">) == </span><span class="identifier-syntax">with</span><span class="plain-syntax">))</span>
<span class="plain-syntax">                </span><a href="2-cmp.html#SP4" class="function-link"><span class="function-syntax">Compatibility::add_exception</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">C</span><span class="plain-syntax">, </span><span class="identifier-syntax">VM</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">current_family</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">family_used</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP10">&#167;10</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP10_3" class="paragraph-anchor"></a><b>&#167;10.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Construe token as a family name subject to debugging</span><span class="named-paragraph-number">10.3</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">seen</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-tvm.html#SP15" class="function-link"><span class="function-syntax">TargetVMs::compatible_with</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="identifier-syntax">token</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">seen</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-tvm.html#SP10" class="function-link"><span class="function-syntax">TargetVMs::debug_enabled</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">) == </span><span class="identifier-syntax">with</span><span class="plain-syntax">)</span>
<span class="plain-syntax">                </span><a href="2-cmp.html#SP4" class="function-link"><span class="function-syntax">Compatibility::add_exception</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">C</span><span class="plain-syntax">, </span><span class="identifier-syntax">VM</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">current_family</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">family_used</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">seen</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP10">&#167;10</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP10_4" class="paragraph-anchor"></a><b>&#167;10.4. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Construe token as a family name</span><span class="named-paragraph-number">10.4</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-tvm.html#SP15" class="function-link"><span class="function-syntax">TargetVMs::compatible_with</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="identifier-syntax">token</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">current_family</span><span class="plain-syntax"> = </span><a href="2-tvm.html#SP15" class="function-link"><span class="function-syntax">TargetVMs::family</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP10">&#167;10</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP10_5" class="paragraph-anchor"></a><b>&#167;10.5. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Construe the token as the end-marker</span><span class="named-paragraph-number">10.5</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">family_used</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">current_family</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-tvm.html#SP15" class="function-link"><span class="function-syntax">TargetVMs::compatible_with</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">current_family</span><span class="plain-syntax">))</span>
<span class="plain-syntax">                </span><a href="2-cmp.html#SP4" class="function-link"><span class="function-syntax">Compatibility::add_exception</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">cps</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">C</span><span class="plain-syntax">, </span><span class="identifier-syntax">VM</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-cmp.html#SP10">&#167;10</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. Testing.</b></p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::test</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">Compatibility::test</span></span>:<br/><a href="2-cmp.html#SP12">&#167;12</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VM</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">C</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">decision</span><span class="plain-syntax"> = </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">default_allows</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">, </span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">exceptions</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">VM</span><span class="plain-syntax"> == </span><span class="identifier-syntax">X</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">decision</span><span class="plain-syntax"> = </span><span class="identifier-syntax">decision</span><span class="plain-syntax">?</span><span class="identifier-syntax">FALSE:TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">decision</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::test_universal</span><span class="plain-syntax">(</span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">C</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">LinkedLists::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">exceptions</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">C</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">default_allows</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>&#167;12. </b>This tests whether at least one VM of the given architecture is compatible.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Compatibility::test_architecture</span><span class="plain-syntax">(</span><span class="reserved-syntax">compatibility_specification</span><span class="plain-syntax"> *</span><span class="identifier-syntax">C</span><span class="plain-syntax">, </span><span class="reserved-syntax">inter_architecture</span><span class="plain-syntax"> *</span><span class="identifier-syntax">A</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax"> *</span><span class="identifier-syntax">VM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="reserved-syntax">target_vm</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="2-cmp.html#SP11" class="function-link"><span class="function-syntax">Compatibility::test</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">C</span><span class="plain-syntax">, </span><span class="identifier-syntax">VM</span><span class="plain-syntax">)) &amp;&amp; (</span><a href="2-tvm.html#SP10" class="function-link"><span class="function-syntax">TargetVMs::has_architecture</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">VM</span><span class="plain-syntax">, </span><span class="identifier-syntax">A</span><span class="plain-syntax">)))</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="2-tvm.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-am.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresssection"><a href="2-arc.html">arc</a></li><li class="progresssection"><a href="2-tvm.html">tvm</a></li><li class="progresscurrent">cmp</li><li class="progresschapter"><a href="3-fm.html">3</a></li><li class="progressnext"><a href="3-fm.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

